/*
 * chunk_buf.cpp
 *
 *  Created on: Mar 29, 2013
 *      Author: root
 */

#include "chunk_buf.h"

chunk_buf::chunk_buf()
{
	current_chunk_count = 0;
	buf = NULL;
}

chunk_buf::~chunk_buf()
{
	chunk * ptr = NULL;
	while(this->free_chunk_pool.size() > 0)
	{
		ptr = this->free_chunk_pool.top();
		this->free_chunk_pool.pop();

		if(ptr != NULL)
		{
			ptr->pData = NULL;
			delete ptr;
			ptr = NULL;
		}
	}

	if(buf != NULL)
		delete [] buf;
}

int chunk_buf::init(uint16_t init_chunk_count,uint24_t chunk_buf_max_size)
{
	if(init_chunk_count == 0 || chunk_buf_max_size == 0)
		return FAILURE;

	int max_buf_size = init_chunk_count * chunk_buf_max_size;
	buf = new unsigned char[max_buf_size];
	if(buf == NULL)
		return FAILURE;

	memset(buf,NULL,max_buf_size);
	chunk * pNewChunk = NULL;
	for(int i=0; i < init_chunk_count; i++)
	{
		pNewChunk = new chunk();
		if(pNewChunk == NULL)
			return FAILURE;

		pNewChunk->pData = buf + i * chunk_buf_max_size;
		pNewChunk->buf_size = chunk_buf_max_size;
		free_chunk_pool.push(pNewChunk);
	}

	return SUCCESS;
}


int chunk_buf::alloc(chunk **pck,size_t buf_size)
{
	int ret  =  FAILURE;
	this->buf_lock.Lock();
	{
		if(this->free_chunk_pool.size() > 0)
		{
			(*pck) = this->free_chunk_pool.top();
			this->free_chunk_pool.pop();

			this->current_chunk_count ++;
			ret = SUCCESS;
		}
		else
		{
			(*pck) = new chunk();
			if((*pck)  == NULL)
			{
				this->buf_lock.Unlock();
				return ret;
			}
			(*pck)->pData = new  ubyte[buf_size];
			if((*pck)->pData  == NULL)
			{
				delete (*pck);
				(*pck) = NULL;

				this->buf_lock.Unlock();
				return ret;
			}

			(*pck)->buf_size = (uint24_t)buf_size;
			this->current_chunk_count ++;
			ret = SUCCESS;
		}
		this->buf_lock.Unlock();
	}

	return ret;
}

int chunk_buf::free(chunk *pck)
{
	if(pck == NULL)
		return FAILURE;

	this->buf_lock.Lock();
	{
		pck->streamid = 0;
		pck->fmt = 0;
		pck->clip_index = 0;
		pck->index= 0;
		pck->length = 0;
		pck->tm_year = 0;
		pck->tm_month = 0;
		pck->tm_day = 0;

		memset(pck->pData,NULL,pck->buf_size);
		pck->offset = 0;
		pck->buf_size = 0;

		pck->next = NULL;
		pck->prev = NULL;

		this->free_chunk_pool.push(pck);

		this->current_chunk_count --;

		this->buf_lock.Unlock();
	}

	return SUCCESS;
}

int chunk_buf::get_current_count(void)
{
	return this->current_chunk_count;
}

int chunk_buf::get_free_count(void)
{
	return (int)this->free_chunk_pool.size();
}
